/**
 * Company : SIANGKLOM.
 * Created By : Chatree Siangklom
 * Created On : Nov 27, 2013  4:34:21 PM 
 * e-Mail : dr_chatree@hotmail.com
 * Mobile Phone : (+66) 087-921-5115
 * Package Name : history.logs
 * File Name : ConsoleHitsLogs.java
 * TODO
 */
package history.logs;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.util.Date;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * @author Chatree Siangklom of Administrator
 * Date =Nov 27, 2013 : 4:34:21 PM 
 * CreateBy=Chatree Siangklom
 * 
 * ConsoleHitsLogs
 * TODO
 */
public class ConsoleHitsLogs extends WindowAdapter implements WindowListener, ActionListener, Runnable
{
	long irow = 0;
	boolean pause = false;
	private JFrame frame;
	private JTextArea textArea;
	private Thread reader;
	private Thread reader2;
	private boolean quit;
	JButton btnPause = null;
	private final PipedInputStream pin = new PipedInputStream();
	private final PipedInputStream pin2 = new PipedInputStream();
	Thread errorThrower; // just for testing (Throws an Exception at this Console
	
	/**
	 * 
	 * Date =Nov 19, 2013 : 10:16:31 AM 
	 * CreateBy=Chatree Siangklom
	 * Console
	 * TODO
	 */
	public ConsoleHitsLogs()
	{
		// create all components and add them
		frame=new JFrame("PROMIS interface LogsHit v1.0");
		Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
		Dimension frameSize=new Dimension((int)(screenSize.width / 2),(int)(screenSize.height / 2));
		int x=(int) (frameSize.width / 2);
		int y=(int) (frameSize.height / 2);
		frame.setBounds(x, y, frameSize.width, frameSize.height);
		frame.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("tis_new_logo.png")));
		
		textArea=new JTextArea();
		textArea.setEditable(false);
		
		//--------------------------------->
		//textArea.setFont(new Font("Serif", Font.PLAIN, 14));
		textArea.setFont(new Font("Tahoma", Font.PLAIN, 12));
		frame.setBackground(Color.BLACK);
		frame.setForeground(Color.WHITE);
		textArea.setForeground(Color.WHITE);
		textArea.setBackground(Color.BLACK);
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);
		//--------------------------------->
		JButton button = new JButton("Clear");
		button.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("trash.png"))));
		
		btnPause = new JButton("Play/Pause");
		btnPause.setActionCommand("PLAY_OR_PAUSE");
		btnPause.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("pause.png"))));
		
		frame.getContentPane().setLayout(new BorderLayout());
		frame.getContentPane().add(new JScrollPane(textArea), BorderLayout.CENTER);
		frame.getContentPane().add(button, BorderLayout.NORTH);
		frame.getContentPane().add(btnPause, BorderLayout.SOUTH);
		frame.setVisible(true);
		
		frame.addWindowListener(this);
		button.addActionListener(this);
		btnPause.addActionListener(this);
		
		try
		{
			PipedOutputStream pout=new PipedOutputStream(this.pin);
			System.setOut(new PrintStream(pout, true)); 
		} 
		catch (java.io.IOException io)
		{
			textArea.append("Couldn't redirect STDOUT to this console\n" + io.getMessage());
		}
		catch (SecurityException se)
		{
			textArea.append("Couldn't redirect STDOUT to this console\n" + se.getMessage());
	    } 
		
		try 
		{
			PipedOutputStream pout2=new PipedOutputStream(this.pin2);
			System.setErr(new PrintStream(pout2,true));
		} 
		catch (java.io.IOException io)
		{
			textArea.append("Couldn't redirect STDERR to this console\n"+io.getMessage());
		}
		catch (SecurityException se)
		{
			textArea.append("Couldn't redirect STDERR to this console\n"+se.getMessage());
	    } 		
			
		quit = false; // signals the Threads that they should exit
				
		// Starting two seperate threads to read from the PipedInputStreams
		reader=new Thread(this);
		reader.setDaemon(true);	
		reader.start();	

		reader2=new Thread(this);	
		reader2.setDaemon(true);	
		reader2.start();
				
		// testing part
		// you may omit this part for your application
		System.out.println("Hello World 2");
		System.out.println("All fonts available to Graphic2D:\n");
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		String[] fontNames=ge.getAvailableFontFamilyNames();
		for(int n=0;n<fontNames.length;n++)  System.out.println(fontNames[n]);		
		// Testing part: simple an error thrown anywhere in this JVM will be printed on the Console
		// We do it with a seperate Thread becasue we don't wan't to break a Thread used by the Console.
		System.out.println("\nLets throw an error on this console");	
		errorThrower=new Thread(this);
		errorThrower.setDaemon(true);
		errorThrower.start();
	}
	
	/*
    private static ImageIcon loadImageIcon(String path) {
        URL imgURL = FrameWithIcon.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }
	*/
	
	/**
	 * (Javadoc)
	 * @see java.awt.event.WindowAdapter#windowClosed(java.awt.event.WindowEvent)
	 * Date =Nov 19, 2013 : 10:16:13 AM 
	 * CreateBy=Chatree Siangklom
	 * TODO
	 */
	public synchronized void windowClosed(WindowEvent evt)
	{
		System.out.println("windowClosed");
		quit=true;
		this.notifyAll(); // stop all threads
		try { reader.join(1000);pin.close();   } catch (Exception e){}		
		try { reader2.join(1000);pin2.close(); } catch (Exception e){}
		System.exit(0);
	}		
	
	/**
	 * (Javadoc)
	 * @see java.awt.event.WindowAdapter#windowClosing(java.awt.event.WindowEvent)
	 * Date =Nov 19, 2013 : 10:16:17 AM 
	 * CreateBy=Chatree Siangklom
	 * TODO
	 */
	public synchronized void windowClosing(WindowEvent evt)
	{
		System.out.println("windowClosing");
		frame.setVisible(false); // default behaviour of JFrame	
		frame.dispose();
	}
	
	/**
	 * (Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 * Date =Nov 19, 2013 : 10:16:19 AM 
	 * CreateBy=Chatree Siangklom
	 * TODO
	 */
	public synchronized void actionPerformed(ActionEvent evt)
	{		
		  String action = evt.getActionCommand();
		  System.out.println("action :" + action +"//actionPerformed :" + new Date().toString());

	        if ("PLAY_OR_PAUSE".equals(action)) {
	        	if(pause) {
	        		pause = false;
	        		btnPause.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("pause.png"))));
	        	}
	        	else {
	        		pause = true;
	        		btnPause.setIcon(new ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("play.png"))));
	        	}
	        }else if ("Clear".equals(action)){	        	
	    		textArea.setText("");
	        }
	}
	
	/**
	 * (Javadoc)
	 * @see java.lang.Runnable#run()
	 * Date =Nov 18, 2013 : 10:52:16 AM 
	 * CreateBy=Chatree Siangklom
	 * TODO
	 */
	public synchronized void run()
	{
		try{
			try
			{
				while (Thread.currentThread()==reader)
				{
					try { this.wait(100);}catch(InterruptedException ie) {}
					if (pin.available()!=0)
					{						
						String input=this.readLine(pin);
						irow ++;
						textArea.append(irow + "." + input);
						
						if(!pause)
							textArea.setCaretPosition(textArea.getDocument().getLength());
						
						if(irow > 500){
							irow = 0;
							textArea.setText("");
						}
					}
					if (quit) return;
				}
			
				while (Thread.currentThread()==reader2)
				{
					try { this.wait(100);}catch(InterruptedException ie) {}
					if (pin2.available()!=0)
					{
						String input=this.readLine(pin2);
						irow ++;
						textArea.append(irow + "." + input);
						
						if(!pause)
							textArea.setCaretPosition(textArea.getDocument().getLength());
						
						if(irow > 500){
							irow = 0;
							textArea.setText("");
						}
					}
					if (quit) return;
				}			
			} catch (Exception e)
			{
				textArea.append("\nConsole reports an Internal error.");
				textArea.append("The error is: " + e);
			}
			
			// just for testing (Throw a Nullpointer after 1 second)
			if (Thread.currentThread()==errorThrower)
			{
				try { this.wait(1000); } catch(InterruptedException ie){}
				throw new NullPointerException("Application test: throwing an NullPointerException It should arrive at the console");
			}
		}finally{
			
			textArea.setCaretPosition(textArea.getDocument().getLength());
		}
	}
	
	/**
	 * 
	 * Date =Nov 18, 2013 : 10:52:10 AM 
	 * CreateBy=Chatree Siangklom
	 * String
	 * TODO
	 * @param in
	 * @return
	 * @throws IOException
	 */
	public synchronized String readLine(PipedInputStream in) throws IOException
	{
		//System.out.println("readLine --->");
		String input="";
		do
		{
			int available=in.available();
			if (available == 0) break;
			byte b[] = new byte[available];
			in.read(b);
			input = input + new String(b,0,b.length);														
		}while( !input.endsWith("\n") && !input.endsWith("\r\n") && !quit);
		return input;
	}
		
	/**
	 * 
	 * Date =Nov 18, 2013 : 10:52:06 AM 
	 * CreateBy=Chatree Siangklom
	 * void
	 * TODO
	 * @param arg
	 */
	public static void main(String[] arg)
	{
		new ConsoleHitsLogs();
		try {
			
			new QueueServerThreadPool().logsHitsThreads();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}			
}